using com.youzu.got.protocol;
using DG.Tweening;
using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using WorldMap.CameraController;
using WorldMapBase;
using WorldMapBase.Tile.Pool;
using XLua;
using Yoozoo.Gameplay.RTS.Proto;
using Yoozoo.Mars.Got.SpriteAnim;
using Yoozoo.UI.YGUI;
using Object = UnityEngine.Object;
using AudioStudio;
using DG.Tweening.Core;
using DG.Tweening.Plugins.Options;
using Yoozoo.Managers.ResourceManagerV2.Runtime;
using Gameplay.RTS.ScriptConfig;
using Neonagee.LocalPreferences;
using UnityEngine.Diagnostics;
using Yoozoo.Gta.Common;

namespace Yoozoo.Gameplay.RTS
{
    //lua 调用c#的方法
    public class RTSLuaCallCSharpManager
    {
        public static bool useGpuFlyText = true;
        public static bool IsTest = false;
        public static int lodLevel;
        public static int marchLodLevel;
        public static float lodScale;
        private static Dictionary<int, MarchLinePoint> pathPointDict = new Dictionary<int, MarchLinePoint>(200);
        public static bool IsRtsUnitTest = false;
        public int LangId;
        /// <summary>
        /// 沙盘总模型到达多少隐藏阴影
        /// </summary>
        public static int MaxModelWithShadow;

        /// <summary>
        /// 沙盘总模型最多到多少
        /// </summary>
        public static int MaxModelWithoutShadow;

        public static void TryLoadResource(int id)
        {
            if (id > 0)
            {
                ArmyManager.TryLoadResource(id);
            }
        }

        public static GameObject GetResourceById(int id, bool isForceGet = false)
        {
            return ArmyManager.GetResourceById(id, isForceGet);
        }

        public static void RecoverResourceById(int id, GameObject obj)
        {
            ArmyManager.RecoverResourceById(id, obj);
        }

        public static GameObject GetEffectById(int id, bool isRelatedToSelf = false)
        {
            return ArmyManager.GetEffectById(id, isRelatedToSelf);
        }

        public static void RecoverEffectById(int id, GameObject obj,bool isRelatedToSelf = false)
        {
            ArmyManager.RecoverEffectById(id,obj,isRelatedToSelf);
        }
        
        public static void InitTeamColor(Color[] teamColors, Color[] teamTxtColors)
        {
            MarchHelper.TeamColors = teamColors;
            MarchHelper.TeamTxtColors = teamTxtColors;
        }

        public static void InitShadowColor(Color[] shadowColors)
        {
            MarchHelper.ShadowColors = shadowColors;
        }
        public static int DrawLine(float startx, float startz, float endx, float endz,int targetTeam)
        {
            
            var info = RTSClassPoolManager.GetLineInfo();
            switch (targetTeam)
            {
                case 0:
                    info.color = BattleUtils.GetColorByType(targetTeam);
                    break;
                case 1:
                    info.color = BattleUtils.GetColorByType(targetTeam);
                    break;
                case 2:
                    info.color = BattleUtils.GetColorByType(targetTeam);
                    break;
                case 3:
                    info.color = Color.white;
                    break;
                default:
                    info.color = Color.white;
                    break;
            }
            
            info.lineType = LineType.line;
            info.speed = 1;
            info.isPart = true;
            info.isHeadPart = true;
            info.startPos = new Vector2(startx, startz);
            info.endPos = new Vector2(endx, endz);
            info.team = 3;

            return (int)DrawLineTool.GetInstance().AddLine(info);
        }

        public static void DelLine(int id)
        {
            DrawLineTool.GetInstance().DelLine((uint) id);
        }

        public static int DrawMarchLine(LuaTable pathList, int startIndex, int team)
        {
            List<Vector2> pointList = new List<Vector2>();
            for (int i = startIndex; i <= pathList.Length; i++)
            {
                var point = pathList.Get<int, Vector3>(i);
                if (point != null)
                {
                    double x = (double) point.x;
                    double z = (double) point.z;
                    pointList.Add(new Vector2
                    {
                        x = (float) x,
                        y = (float) z,
                    });
                }
            }

            var info = RTSClassPoolManager.GetLineInfo();
            info.color = BattleUtils.GetColorByType(team);
            info.lineType = LineType.arrow;
            info.speed = 1;
            info.isPart = true;
            info.isHeadPart = true;
            info.team = team;
            
            var lineId = (int) DrawLineTool.GetInstance().AddMultiLines(info, pointList);
            if (pointList.Count > 1)
            {
                ShowMarchPathPoint(lineId, pointList[0], pointList[pointList.Count - 1], info.color,team);
            }

            return lineId;
        }

        public static int DrawMarchLine(List<Vector3> points, int startIndex, int team,bool isGather,bool isWonderNpc = false,bool isBKIARMYNpc = false)
        {
            var line = RTSClassPoolManager.GetLineInfo();
            if (isBKIARMYNpc)
            {
                line.color = new Color(127f/255f, 0, 0);
            }
            else
            {
                line.color = BattleUtils.GetColorByType(team);
            }
            if (isGather)
            {
                line.lineType = LineType.assembly;
            }
            else if (isWonderNpc)
            {
                line.lineType = LineType.wonderNpc;
            }
            else
            {
                line.lineType = LineType.arrow;
            }
            line.speed = 1;
            line.isPart = true;
            line.isHeadPart = true;
            line.team = team;
            float scale = 1f;
            if (team == 0 || isWonderNpc)
            {
                scale = DrawLineTool.GetInstance().selfScale;
            }
            var lineId = (int) DrawLineTool.GetInstance().AddMultiLines(line,startIndex, points);
            if (points.Count > 1)
            {
                var startPos = new Vector2(points[0].x, points[0].z);
                var endPos = new Vector2(points[points.Count - 1].x,points[points.Count - 1].z);
                ShowMarchPathPoint(lineId, startPos, endPos, line.color,team,scale);
            }
            RTSClassPoolManager.RecoverLineInfo(line);
            return lineId;
        }

        public static void DelMarchLine(int id)
        {
            HideMarchPathPoint(id);
            DrawLineTool.GetInstance().DelMultiLines((uint) id);
        }

        public static int DrawWarningLine(float startX,float startZ, float endX,float endZ, int team)
        {
            var line = RTSClassPoolManager.GetLineInfo();
            line.color = BattleUtils.GetColorByType(team);
            line.speed = 1;
            line.isPart = true;
            line.isHeadPart = false;
            line.lineType = LineType.warning;
            List<Vector2> pointList = new List<Vector2>();
            pointList.Add(new Vector2(startX,startZ));
            pointList.Add(new Vector2(endX,endZ));
            var lineId = (int) DrawLineTool.GetInstance().AddMultiLines(line,pointList); 
            ShowWarningEndPoint(lineId,new Vector2(endX,endZ),line.color);
            RTSClassPoolManager.RecoverLineInfo(line);
            return lineId;
        }

        public static void DelWarningLine(int id)
        {
            HideWarningEndPoint(id);
            DrawLineTool.GetInstance().DelMultiLines((uint) id);
        }
        
        public static void LockCamera(int key)
        {
            CameraMoveLockMgr.LockCameraMove(key);
        }

        public static void UnLockCamera(int key)
        {
            CameraMoveLockMgr.UnLockCameraMove(key);
        }

        public static void ShowSkillDirector(int team,int releasePosMark, int target_team,int director_type, Dictionary<string, float> param, Vector3 selfPosition,
            Vector3 targetPosition, float directorTime = 1f, bool isArea = false)
        {
            Vector3 forward = targetPosition - selfPosition;
            if (releasePosMark == 1)
            {
                selfPosition = targetPosition;
            }
           
            if (target_team == 2 && director_type == 2)
            {
                targetPosition = selfPosition;
            }

            RTSBattleEffectManager.ShowSkillDirectorByType(team, (int) director_type,forward, param, selfPosition,
                targetPosition, directorTime, isArea);
        }

        public static int PlayEffect(int effectId, Vector3 selfPosition, Vector3 targetPosition,int team,bool isRelatedToSelf = false,bool needChangeEffectColor = false)
        {
            var isOverloaded = RTSQualityHelper.CheckIsEffectOverloaded(isRelatedToSelf);
            if (isOverloaded)
            {
                return -1;
            }

            if (isRelatedToSelf)
            {
                RTSQualityHelper.SelfEffectUsingCount++;
            }
            else
            {
                RTSQualityHelper.OtherEffectUsingCount++;
            }
            return RTSBattleEffectManager.Instance.PlayEffect(effectId, selfPosition, targetPosition,team,needChangeEffectColor);
        }

        public static int PlayBuffEffect(int effectId,MarchEntity march,bool isRelatedToSelf = false)
        {
            var isOverloaded = RTSQualityHelper.CheckIsEffectOverloaded(isRelatedToSelf);
            if (isOverloaded)
            {
                return -1;
            }

            if (isRelatedToSelf)
            {
                RTSQualityHelper.SelfEffectUsingCount++;
            }
            else
            {
                RTSQualityHelper.OtherEffectUsingCount++;
            }

            return RTSBattleEffectManager.Instance.PlayBuffEffect(effectId, march.Mono.transform);
        }

        public static int PlayEffectAndSound(int effectId,long marchId,TargetCoordinateType type, long targetId,TargetCoordinateType targetType,bool isRelatedToSelf,int team,string sound,string sound2,bool needChangeEffectColor = false)
        {
            var marchEntity = ArmyManager.Instance.MarchManager.GetMarchEntityByIdAndType(marchId,type);
            Vector3 selfPosition = default;
            Vector3 targetPosition = default;
            MarchEntity targetEntity = null;
            if (targetId!=0)
            {
                targetEntity = ArmyManager.Instance.MarchManager.GetMarchEntityByIdAndType(targetId,targetType);
                if (targetEntity != null)
                {
                    targetPosition = targetEntity.Position;
                }
            }
            if (marchEntity != null)
            {
                selfPosition = marchEntity.Position;
                var targetTeam = -1;
                if (targetEntity != null)
                {
                    targetTeam = targetEntity.Team;
                }
                if (ArmyManager.Instance.CanPlayAudio(marchEntity.Team,targetTeam))
                {
                    if (!string.IsNullOrEmpty(sound))
                    {
                        AudioManager.PlaySound(sound, marchEntity.GetAudioEmiterObject());
                    }
                    if (!string.IsNullOrEmpty(sound2))
                    {
                        AudioManager.PlaySound(sound2, marchEntity.GetAudioEmiterObject());
                    }
                }
            }
            

            if (targetPosition == default)
            {
                targetPosition = selfPosition;
            }
            return PlayEffect(effectId, selfPosition, targetPosition,team, isRelatedToSelf,needChangeEffectColor);
        }
        public static int PlayAreaEffect(int effectId, Vector3 selfPosition, Vector3 targetPosition, float duration,bool isRelatedToSelf = false)
        {
            var isOverloaded = RTSQualityHelper.CheckIsEffectOverloaded(isRelatedToSelf);
            if (isOverloaded)
            {
                return -1;
            }

            if (isRelatedToSelf)
            {
                RTSQualityHelper.SelfEffectUsingCount++;
            }
            else
            {
                RTSQualityHelper.OtherEffectUsingCount++;
            }
            return RTSBattleEffectManager.Instance.PlayAreaEffect(effectId, selfPosition, targetPosition, duration);
        }

        public static void RemoveEffect(int effectId,bool isRelatedToSelf = false)
        {
            if (effectId >= 0)
            {
                if (isRelatedToSelf)
                {
                    RTSQualityHelper.SelfEffectUsingCount--;
                }
                else
                {
                    RTSQualityHelper.OtherEffectUsingCount--;
                }
            }

            RTSBattleEffectManager.Instance.RemoveEffect(effectId);
        }
        public static int FlyText(int type, Vector3 position, string content, float scale,
            Vector3 targetPosition, string tid, int priority, FlyTextAudio audioType = FlyTextAudio.NONE,string PlayAnimName = default)
        {
            if (useGpuFlyText)
            {
                if (!GpuFlyTextHelper.PlayFlyText(type, position, 0.89f, content))
                {
                    return FlyTextManager.Play(type, position, content, scale, targetPosition, priority, audioType,PlayAnimName);
                }

                return -1;
            }
            else
            {
                return FlyTextManager.Play(type, position, content, scale, targetPosition, priority, audioType,PlayAnimName);
            }
        }
        public static int FlyTextIcon(int type, Vector3 position, string content, string icon, int priority = 0) {
            return FlyTextManager.PlayFlyTextIcon(type, position, content, icon, priority);
        }

        public static int PlayRepeatText(int type, string numChar,int content, float scale, string animName,List<int> intervalArray, Vector3 position, Vector3 targetPosition = default, int priority = 0)
        {
            return FlyTextManager.PlayRepeatText(type, numChar,content, scale,animName, intervalArray,position, targetPosition,priority);
        }
        
        // 20240924 艾德新增的显示伤害飘字的方法
        public static int PlayRepeatText2(int type, string numChar,int content, float scale, string animName,List<Vector2Int> intervalArray, Vector3 position, Vector3 targetPosition = default, int priority = 0)
        {
            return FlyTextManager.PlayRepeatText2(type, numChar,content, scale,animName, intervalArray,position, targetPosition,priority);
        }
        /// <summary>
        /// 播放技能名字飘字，在头像处
        /// </summary>
        /// <param name="type"></param>
        /// <param name="tid"></param>
        /// <param name="content"></param>
        /// <returns></returns>
        public static int FlyTextName(int team,long tid,TargetCoordinateType type, string content,float offsetX = 0,float offsetY = 0,float offsetZ = 0, int priority = 0,bool isCarSkill = false, string icon = null)
        {
            var march = ArmyManager.Instance.MarchManager.GetMarchEntityByIdAndType(tid,type);
            if (march != null)
            {
                var target = march.GetBattleTarget();
                Vector3 targetPosition;
                if (target != null)
                {
                    targetPosition = target.Position;
                }
                else
                {
                    targetPosition = march.Position;
                }
                if (march.Hud != null && march.Hud.MarchHudLod0!= null)
                {
                    if (march.Hud.Alpha == 1)//只有头像显示的时候，才会飘字
                    {
                        var finalPos = march.Hud.commanderHead;
                        Vector3 offset= default;
                    
                        targetPosition = WorldCameraManager.mainCamera.WorldToScreenPoint(targetPosition);
                        Vector3 myPos = WorldCameraManager.mainCamera.WorldToScreenPoint(march.Position);
                        int textType;
                        if (targetPosition.x > myPos.x) //我方在左边
                        {
                            if (!isCarSkill)
                            {
                                if (finalPos!=null)
                                {
                                    offset = finalPos.LeftPos.position;
                                }
                                textType = 2001;
                            }
                            else
                            {
                                if (finalPos!=null)
                                {
                                    offset = finalPos.LeftPos.position;
                                }
                                textType = 4001;
                            }
                        }
                        else
                        {
                            if (!isCarSkill)
                            {
                                if (finalPos != null)
                                {
                                    offset = finalPos.RightPos.position;
                                }
                                textType = 2000;  
                            }
                            else
                            {
                                if (finalPos != null)
                                {
                                    offset = finalPos.RightPos.position;
                                }
                                textType = 4002;
                            }
                        }

                        var offset2 = new Vector3(offsetX, offsetY, offsetZ);
                    
                        return FlyTextManager.PlaySkill(textType, team,offset, content,march.Hud.MarchHudLod0.transform.localScale.x / 0.006f,offset2, priority,isCarSkill, icon);
                    }
                    else
                    {
                        return 0;
                    }
                    
                }
                else
                {
                    if (UnityEngine.Debug.isDebugBuild)
                    {
                        Debug.LogError("飘字目标HUD为空");
                    }
                   
                    return 0;
                }
                
            }
            else
            {
                return 0;
            }
        }
        public static void FlyTextFree(int allocId)
        {
            FlyTextManager.Free(allocId);
        }

        public static void PreloadEffectConfig(LuaTable table)
        {
            RTSBattleEffectManager.Instance.PreloadEffectConfig(table);
        }
        
        public static void PreloadBattleFormationConfig(BattleFormationCfgs cfgs)
        {
            BattleFormationHelper.PreloadBattleFormationConfig(cfgs);
        }
        public static void PreloadFlyText(GameObject prefab, int count, int type)
        {
            FlyTextManager.PreloadFlyText(prefab, count, type);
        }
        //TODO: lod相关的应该在C#这边处理，而不是C#-->Lua-->C#
        public static void OnLODPercentUpdate(int lodLevel, int marchLodLevel, float lodScale)
        {
            RTSLuaCallCSharpManager.lodLevel = lodLevel;
            RTSLuaCallCSharpManager.marchLodLevel = marchLodLevel;
            RTSLuaCallCSharpManager.lodScale = lodScale;
            FlyTextManager.OnLODLevelChange(lodScale);

            var marchDatas = ArmyManager.Instance.MarchManager.GetAllMarchEntities();
            foreach (var marchData in marchDatas)
            {
                var square = marchData.GetBattleSquare();
                square?.ResetChildrenScale();
            }
        }

        public static TweenerCore<float,float,FloatOptions> TweenTo(float myValue, Action<float> b, float value, float duration,int easeType = 0)
        {
            var tween = DOTween.To(() => { return myValue; },
                (v) => { b(v); }, value, duration);
            tween.SetEase((Ease) easeType);
            return tween;
        }

        public static void SetUIOverlayMat(GameObject obj, object mat)
        {
            var yImageList = obj.GetComponentsInChildren<YImage>();
            for (int i = 0; i < yImageList.Length; i++)
            {
                yImageList[i].material = mat as Material;
            }

            var yTextList = obj.GetComponentsInChildren<YText>();
            for (int i = 0; i < yTextList.Length; i++)
            {
                yTextList[i].material = mat as Material;
            }

            var imageList = obj.GetComponentsInChildren<Image>();
            for (int i = 0; i < imageList.Length; i++)
            {
                imageList[i].material = mat as Material;
            }

            var textList = obj.GetComponentsInChildren<Text>();
            for (int i = 0; i < textList.Length; i++)
            {
                textList[i].material = mat as Material;
            }
        }

        public static void UpdateFog(bool[] unlockedData)
        {
            RTSTest.UpdateFog(unlockedData);
        }

        public static void UpdateServerTimeStamp(double timeStamp)
        {
            TimeUtils.UpdateServerTimeStamp((long) timeStamp);
        }

        public static void CalMonsterNeedLoadSoldierAtlas(LuaTable soldierList)
        {
            RTSSpriteManager.Inst.CalMonsterNeedLoadSoldierAtlas(soldierList);
        }
        
        public static void PreloadSoldierConfig(LuaTable soldiers_dataConfig, LuaTable rts_soldier_model_configConfig)
        {
            ArmyManager.Instance.ResourceManager.PreloadSoldierConfig(soldiers_dataConfig, rts_soldier_model_configConfig);
        }

        public static void PreloadRTSGlobalValue(float attack_range_1,float chaseAttackOffset)
        {
            MarchHelper.attack_range_1 = attack_range_1;
            MarchHelper.chaseAttackOffset = chaseAttackOffset;
        }

        public static void PreloadHeroSkillConfig(LuaTable hero_skillConfig, LuaTable skill_element_rts_config, LuaTable hero_monsterConfig)
        {
            ArmyManager.Instance.ResourceManager.PreloadSkillConfig(hero_skillConfig, skill_element_rts_config, hero_monsterConfig);
        }

        public static void PreloadQualityLevelConfig(LuaTable rts_quality_levelConfig)
        {
            ArmyManager.Instance.ResourceManager.PreloadQualityLevelConfig(rts_quality_levelConfig);
        }

        public static void PreloadFormationSoldierPositionCfg(LuaTable formationSoldierPositionCfg)
        {
            ArmyManager.Instance.ResourceManager.PreloadFormationSoldierPositionCfg(formationSoldierPositionCfg);
            SquareDataManager.Instance.InitSoldierIndex();
        }
        public static void PreloadRTSNeedLangConfig(LuaTable LangConfig)
        {
            ArmyManager.Instance.ResourceManager.PreloadRTSNeedLangConfig(LangConfig);
        }

        public static void PreloadRTSNeedItemConfig(LuaTable ItemConfig) 
        {
            ArmyManager.Instance.ResourceManager.PreloadRTSNeedItemConfig(ItemConfig);
        }

        public static void StopTestBattle()
        {
            RTSTest.StopAutoBattleSync();
        }
        /// <summary>
        /// 显示行军当前起始点和结束点两个端点图标
        /// </summary>
        /// <param name="lineId">所属行军线的ID</param>
        /// <param name="startPos">当前行军起始点</param>
        /// <param name="endPos">行军目标点</param>
        private static void ShowMarchPathPoint(int lineId, Vector2 startPos, Vector2 endPos, Color color,int team,float scale = 1)
        {
            if (pathPointDict.ContainsKey(lineId))
            {
                HideMarchPathPoint(lineId);
            }
            var marchLinePoint = RTSClassPoolManager.GetMarchLinePoint();
            marchLinePoint.lineId = lineId;
            
            pathPointDict.Add(lineId, marchLinePoint);

            var pathStartObj = ArmyManager.GetResourceById(404);
            pathStartObj.transform.SetParent(DrawLineTool.GetInstance().transform);
            marchLinePoint.pathStartObj = pathStartObj;


            pathStartObj.GetComponentsInChildren(marchLinePoint.imageStart);
            if (marchLinePoint.imageStart != null)
            {
                foreach (var item in marchLinePoint.imageStart)
                {
                    item.color = color;
                }
            }


            var pathEndObj = ArmyManager.GetResourceById(405);
            marchLinePoint.pathEndObj = pathEndObj;
            pathEndObj.transform.SetParent(DrawLineTool.GetInstance().transform);
            pathEndObj.GetComponentsInChildren(marchLinePoint.imageEnd);

            if (marchLinePoint.imageEnd != null)
            {
                foreach (var item in marchLinePoint.imageEnd)
                {
                    item.color = color;
                }
            }
            pathStartObj.transform.position = new Vector3(startPos.x, 0.001f, startPos.y);
            pathEndObj.transform.position = new Vector3(endPos.x, 0.001f, endPos.y);

            var scaleTimes = DrawLineTool.pointScale * scale;
            
            pathStartObj.transform.localScale = new Vector3(scaleTimes, scaleTimes, scaleTimes);
            pathEndObj.transform.localScale = new Vector3(scaleTimes, scaleTimes, scaleTimes);
            
        }

        public static void ChangeMarchPathPointColor(int lineId, Color color)
        {
            if (pathPointDict.TryGetValue(lineId,out var points))
            {
                var imageStart = points.imageStart;
                if (imageStart != null)
                {
                    foreach (var item in imageStart)
                    {
                        item.color = color;
                    }
                }

                var imageEnd = points.imageEnd;
                if (imageEnd != null)
                {
                    foreach (var item in imageEnd)
                    {
                        item.color = color;
                    }
                }
            }
        }
        private static void HideMarchPathPoint(int lineId)
        {
            MarchLinePoint linePoint;
            if (pathPointDict.TryGetValue(lineId, out linePoint))
            {
                ArmyManager.RecoverResourceById(404, linePoint.pathStartObj);
                ArmyManager.RecoverResourceById(405, linePoint.pathEndObj);
                linePoint.pathStartObj = null;
                linePoint.pathEndObj = null;
                RTSClassPoolManager.RecoverMarchLinePoint(pathPointDict[lineId]);
                pathPointDict.Remove(lineId);
            }
        }
        

        private static void ShowWarningEndPoint(int lineId,Vector3 pos,Color color)
        {
            if (pathPointDict.ContainsKey(lineId))
            {
                HideWarningEndPoint(lineId);
            }
            var marchLinePoint = RTSClassPoolManager.GetMarchLinePoint();
            marchLinePoint.lineId = lineId;
            
            pathPointDict.Add(lineId, marchLinePoint);
            
            var pathEndObj = ArmyManager.GetResourceById(405);
            marchLinePoint.pathEndObj = pathEndObj;
            pathEndObj.transform.SetParent(DrawLineTool.GetInstance().transform);
            pathEndObj.GetComponentsInChildren(marchLinePoint.imageEnd);

            if (marchLinePoint.imageEnd != null)
            {
                foreach (var item in marchLinePoint.imageEnd)
                {
                    item.color = color;
                }
            }
            pathEndObj.transform.position = new Vector3(pos.x, 0.001f, pos.y);

            var scaleTimes = DrawLineTool.pointScale * 1.5f;
            
            pathEndObj.transform.localScale = new Vector3(scaleTimes, scaleTimes, scaleTimes);

        }

        private static void HideWarningEndPoint(int lineId)
        {
            MarchLinePoint linePoint;
            if (pathPointDict.TryGetValue(lineId, out linePoint))
            {
                ArmyManager.RecoverResourceById(405, linePoint.pathEndObj);
                linePoint.pathEndObj = null;
                RTSClassPoolManager.RecoverMarchLinePoint(pathPointDict[lineId]);
                pathPointDict.Remove(lineId);
            }
        }

        /// <summary>
        /// 画质变更后，修改部分参数
        /// </summary>
        /// <param name="maxModelWithShadow"></param>
        /// <param name="maxModelWithoutShadow"></param>
        /// <param name="maxThrowableItem"></param>
        /// <param name="maxSkillEffect"></param>
        public static void OnQualityChanged(int maxModelWithShadow, int maxModelWithoutShadow, int maxThrowableItem, int maxSkillEffect)
        {
            MaxModelWithShadow = maxModelWithShadow;
            MaxModelWithoutShadow = maxModelWithoutShadow;
//            ThrowableManager.MaxCount = maxThrowableItem;
            EffectController.MaxCount = maxSkillEffect;
        }

        public static void OnQualityChangedSprite(int marchCount,int childCount,int particleCount)
        {
            SquareDataManager.SetMaxCount(marchCount,childCount);
            SpriteParticleSystemManager.INITAL_PARTICLE_NUM = particleCount;
        }

        public static void OnQualityChangedEffect(int selfEffect,int othersEffect,int skillEffect)
        {
            RTSQualityHelper.SelfEffectMaxCount = selfEffect;
            RTSQualityHelper.OtherEffectMaxCount = othersEffect;
            EffectController.MaxCount = skillEffect;
        }
        public static void OnQualityChangedMaxTroopNum(int MaxFlyTextTroopNum, int MaxAttackEffectTroopNum, int MaxSkillTroopNum)
        {
            RTSQualityHelper.MaxFlyTextTroopNum = MaxFlyTextTroopNum;
            RTSQualityHelper.MaxAttackEffectTroopNum = MaxAttackEffectTroopNum;
            RTSQualityHelper.MaxSkillTroopNum = MaxSkillTroopNum;
        }

        public static void OnChangeEffectNum(int MaxFlyTextNum,int MaxAttackEffectNum,int MaxSkillEffectNum)
        {
            RTSQualityHelper.MaxFlyTextNum = MaxFlyTextNum;
            RTSQualityHelper.MaxAttackEffectNum = MaxAttackEffectNum;
            RTSQualityHelper.MaxSkillEffectNum = MaxSkillEffectNum;
        }
        public static void OnQualityChangedFlyText(int flyTextCount)
        {
            FlyTextManager.MaxShowNum = flyTextCount;
        }

        public static void OnQualityChanged(int quality)
        {
            RTSQualityHelper.Quality = quality;
        }

        public static void OnCommanderHeadChanged(bool bShow)
        {
            RTSQualityHelper.IsShowCommanderHead = bShow;
        }


        public static void PreloadMapBesiegeConfig(LuaTable table)
        {
            MarchBesiegeManager.Instance.LoadBesiegeConfig(table);
        }

        public static void StartUnitTest()
        {
            RTSUnitTest.Enable = true;
            var rtsMono = Object.FindObjectOfType<RTSMono>();
            if (rtsMono != null)
            {
                rtsMono.gameObject.GetOrAddComponent<RTSUnitTest>();
            }
        }

        public static void EndUnitTest()
        {
            RTSUnitTest.Enable = false;
            var rtsUnitTest = Object.FindObjectOfType<RTSUnitTest>();
            if (rtsUnitTest != null)
            {
                Object.DestroyImmediate(rtsUnitTest);
            }
        }

        public static void InitRtsUnitTest()
        {
            var v = LocalPrefs.GetInt("RtsUnitTest");
            if (v == 1)
            {
                IsRtsUnitTest = true;
                StartUnitTest();
            }
            else
            {
                IsRtsUnitTest = false;
                EndUnitTest();
            }
        }

        public static void SelectBattleTroops(List<Troop> targetIdList, float otherAlpha)
        {
            ArmyManager.Instance.MarchManager.SelectBattleTroops(targetIdList, otherAlpha);
        }
        public static void MoveSelectMarchToNormalCanvas(List<long> targetIdList)
        {
            ArmyManager.Instance.MarchManager.MoveSelectMarchToNormalCanvas(targetIdList);
        }
        public static bool isArmyEnabled = true;
        public static bool isSandboxType1Enabled = true;
        public static bool isSandboxType2Enabled = true;
        public static bool isSandboxType3Enabled = true;
        public static bool isSandboxType4Enabled = true;
        
        public static void SetArmyEnabled(bool enabled)
        {
            isArmyEnabled = enabled;
            if (isArmyEnabled)
            {
                ArmyManager.SpriteParticleSystemManager.SetAllParticleEnable(true);
                ArmyManager.Instance.MarchManager.GetRoot().gameObject.SetActive(true);
//                ArmyManager.Instance.MarchManager.ForceSetSquareChildPosition();
            }
            else
            {
                ArmyManager.Instance.MarchManager.StopAllBattleAudio();
            }

            if (ArmyManager.SpriteParticleSystemManager)
            {
                var particleRoot = ArmyManager.SpriteParticleSystemManager.gameObject;
                if (particleRoot != null)
                {
                    particleRoot.SetActive(enabled);
                }
            }
        }

        public static void SetSandboxTypeEnabled(int type,bool enabled)
        {
            WorldMapConfigData.SetMapDebugChunckEntityNum(type,enabled ? -1 : 0);
        }

        public static bool isSandboxDebug = false;
        
        public static void SetIsSandboxDebug(bool isDebug)
        {
            isSandboxDebug = isDebug;
            WorldMapConfigData.SetMapDebug(isDebug);
        }

        public static bool isMeshRendererEnabled = true;
        public static void SetMeshRendererEnabled(bool isEnabled)
        {
            isMeshRendererEnabled = isEnabled;
            var renderers = GameObject.FindObjectsOfType<MeshRenderer>();
            for (int i = 0; i < renderers.Length; i++)
            {
                var pos = renderers[i].transform.position;
                if (CheckIsInPool(pos))
                {
                    renderers[i].enabled = isEnabled;
                }
            }

            var particles = GameObject.FindObjectsOfType<ParticleSystem>();
            for (int i = 0; i < particles.Length; i++)
            {
                var pos = particles[i].transform.position;
                if (CheckIsInPool(pos))
                {
                    var emission = particles[i].emission;
                    emission.enabled = isEnabled;
                }
            }

            var canvas = GameObject.FindObjectsOfType<Canvas>();
            for (int i = 0; i < canvas.Length; i++)
            {
                var pos = canvas[i].transform.position;
                if (CheckIsInPool(pos))
                {
                    canvas[i].enabled = isEnabled;
                }
            }

            var yimages = GameObject.FindObjectsOfType<YImage>();
            for (int i = 0; i < yimages.Length; i++)
            {
                var pos = yimages[i].transform.position;
                if (CheckIsInPool(pos))
                {
                    yimages[i].enabled = isEnabled;
                }
            }

            var spriteRenderers = GameObject.FindObjectsOfType<SpriteRenderer>();
            for (int i = 0; i < spriteRenderers.Length; i++)
            {
                var pos = spriteRenderers[i].transform.position;
                if (CheckIsInPool(pos))
                {
                    spriteRenderers[i].enabled = isEnabled;
                }
            }

            var animators = GameObject.FindObjectsOfType<Animator>();
            for (int i = 0; i < animators.Length; i++)
            {
                var pos = animators[i].transform.position;
                if (CheckIsInPool(pos))
                {
                    animators[i].enabled = isEnabled;
                }
            }
        }
        
        public static bool isPoolObjectActive = true;

        public static void SetIsPoolObjectActive(bool isActive)
        {
            isPoolObjectActive = isActive;
            var trans = GameObject.FindObjectsOfType<Transform>();
            var meshCount = 0;
            var spriteRendererCount = 0;
            var canvasCount = 0;
            var yimageCount = 0;
            var particleCount = 0;
            var animatorCount = 0;
            for (int i = 0; i < trans.Length; i++)
            {
                var pos = trans[i].localPosition;
                if (CheckIsInPool(pos))
                {
                    var root = trans[i].gameObject;
                    root.SetActive(isActive);
                    if (!isActive)
                    {
                        meshCount += root.GetComponentsInChildren<MeshRenderer>().Length;
                        canvasCount += root.GetComponentsInChildren<Canvas>().Length;
                        spriteRendererCount += root.GetComponentsInChildren<SpriteRenderer>().Length;
                        yimageCount += root.GetComponentsInChildren<YImage>().Length;
                        particleCount += root.GetComponentsInChildren<ParticleSystem>().Length;
                        animatorCount += root.GetComponentsInChildren<Animator>().Length;
                    }
                }
            }
            Debug.LogError("Mesh " + meshCount);
            Debug.LogError("SpriteRenderer " + spriteRendererCount);
            Debug.LogError("Canvas " + canvasCount);
            Debug.LogError("YImage " + yimageCount);
            Debug.LogError("Animator " + animatorCount);
        }
        
        private static bool CheckIsInPool(Vector3 position)
        {
            return position.x <= -90000 || position.y <= -90000 || position.z <= -90000;
        }

        public static void SetCarQuality(int carNum,bool carCheck,bool trafficEnable)
        {
            if (DynamicLayerMgr.worldEntry!=null)
            {
                DynamicLayerMgr.worldEntry.SetCarNum(carNum);
                DynamicLayerMgr.worldEntry.SetCarCheck(carCheck);
                DynamicLayerMgr.worldEntry.SetTrafficOpen(trafficEnable);
            }
        }

        public static void ResetSandboxDecorationQuality(int level)
        {
            DynamicLayerMgr.worldEntry.ResetSandboxDecorationQuality(level);
        }

        public static bool isOutCameraObjectActive = true;
        
        public static void SetOutCameraObjectActive(bool isActive)
        {
            var camera = DynamicLayerMgr.worldEntry.GetCamera();
            isOutCameraObjectActive = isActive;
            var root = WorldDynamicPoolMgr.InstanceRoot;
            for (int i = 0; i < root.childCount; i++)
            {
                var trans = root.GetChild(i);
                var pos = trans.localPosition;
                if (CheckIsOutCamera(camera,pos))
                {
                    trans.gameObject.SetActive(isActive);
                }
            }

            root = WorldPoolManager.TreeRoot;
            for (int i = 0; i < root.childCount; i++)
            {
                var trans = root.GetChild(i);
                var pos = trans.localPosition;
                if (CheckIsOutCamera(camera,pos))
                {
                    trans.gameObject.SetActive(isActive);
                }
            }

            /*root = WorldPoolManager.TerrainRoot;
            for (int i = 0; i < root.childCount; i++)
            {
                var trans = root.GetChild(i);
                var pos = trans.localPosition;
                if (CheckIsOutCamera(camera,pos))
                {
                    trans.gameObject.SetActive(isActive);
                }
            }*/
        }
        
        public static bool isOutCameraObjectRendererActive = true;
        public static void SetOutCameraObjectRendererActive(bool isActive)
        {
            var camera = DynamicLayerMgr.worldEntry.GetCamera();
            isOutCameraObjectActive = isActive;
            var root = WorldDynamicPoolMgr.InstanceRoot;
            var renderers = root.GetComponentsInChildren<MeshRenderer>();
            for (int i = 0; i < renderers.Length; i++)
            {
                var trans = renderers[i].transform;
                var pos = trans.position;
                if (CheckIsOutCamera(camera,pos))
                {
                    renderers[i].enabled = isActive;
                }
            }

            root = WorldPoolManager.TreeRoot;
            renderers = root.GetComponentsInChildren<MeshRenderer>();
            for (int i = 0; i < renderers.Length; i++)
            {
                var trans = renderers[i].transform;
                var pos = trans.position;
                if (CheckIsOutCamera(camera,pos))
                {
                    renderers[i].enabled = isActive;
                }
            }
        }

        public static bool CheckIsOutCamera(Camera camera,Vector3 position)
        {
            var screen = camera.WorldToScreenPoint(position);
            if (screen.x >= Screen.width || screen.y >= Screen.height || screen.x <= 0 || screen.y <= 0)
            {
                return true;
            }
            return false;
        }

        public static void SetTmpRebuildEnabled(bool enabled)
        {
            TMP_UpdateManager.EnableRebuild = true;
        }

        public static void SetPos(GameObject go, Vector3 pos)
        {
            go.transform.position = pos;
        }
        public static void SetForward(GameObject go, Vector3 forward)
        {
            go.transform.forward = forward;
        }

        public static void ResetResourceLoadAgentCount(int agentCount)
        {
            /*var resourceComponents = UnityEngine.GameObject.FindObjectsOfType<ResourceComponent>();
            for (int i = 0; i < resourceComponents.Length; i++)
            {
                resourceComponents[i].ResetAgentCount(agentCount);
            }*/
        }

        public static void SetRapidWhenSwitchScene(bool rapid)
        {
            isRapidWhenSwitchScene = rapid;
            ResLoader.isForceRapid = rapid;
        }


        private static ThreadPriority defaultBackgroundLoadingPriority = Application.backgroundLoadingPriority;
        private static int defaultAupTimeSlice = -1;
        private static int defaultAupBufferSize = -1;
        
        public static void SetIsRapidLoading(bool rapid)
        {
            if (rapid)
            {
                /*Profiler.BeginSample("LoadingTest.GC1");
                GC.Collect();
                GC.Collect();
                GC.Collect();
                Profiler.EndSample();
                Profiler.BeginSample("LoadingTest.AddMemoryPressure");
                GC.AddMemoryPressure(1024 * 50 * 1024);
                Profiler.EndSample();
                Profiler.BeginSample("LoadingTest.GC2");
                GC.Collect();
                GC.Collect();
                GC.Collect();
                Profiler.EndSample();
                Profiler.BeginSample("LoadingTest.NewList");
                var list = new List<byte>();
                for (int i = 0; i < 50 * 1024 * 1024;i++)
                {
                    byte b = 1;
                    list.Add(b);
                }
                list.Clear();
                Profiler.EndSample();
                Profiler.BeginSample("LoadingTest.GC3");
                GC.Collect();
                GC.Collect();
                GC.Collect();
                Profiler.EndSample();*/
            }
            //ResLoader.isForceRapid = rapid;
            if (defaultAupBufferSize == -1)
            {
                defaultAupBufferSize = QualitySettings.asyncUploadBufferSize;
            }

            if (defaultAupTimeSlice == -1)
            {
                defaultAupTimeSlice = QualitySettings.asyncUploadTimeSlice;
            }
            
            isRapidWhenSwitchScene = rapid;
            //ResLoader.isForceRapid = rapid;
            if (rapid)
            {
                Application.backgroundLoadingPriority = ThreadPriority.High;
                QualitySettings.asyncUploadBufferSize = 4;
                QualitySettings.asyncUploadTimeSlice = 33;
                
                
            }
            else
            {
                Application.backgroundLoadingPriority = defaultBackgroundLoadingPriority;
                QualitySettings.asyncUploadBufferSize = defaultAupBufferSize;
                QualitySettings.asyncUploadTimeSlice = defaultAupTimeSlice;
            }
        }
        public static bool isRapidWhenSwitchScene = false;

        public static void ChangeSimpleMode(bool isSimpleModel)
        {
            RTSQualityHelper.ChangeSimpleMode(isSimpleModel,false);
        }

        public static void SetThirdAttackEffect(bool IsShowThirdAttackSpeedLineEffect,
            bool IsShowThirdAttackEffect,
            bool IsShowThirdRageEffect,
            bool IsShowThirdNormalText,
            bool IsShowThirdSkillText)
        {
            SetIsShowThirdAttackSpeedLineEffect(IsShowThirdAttackSpeedLineEffect);
            SetIsShowThirdAttackEffect(IsShowThirdAttackEffect);
            SetIsShowThirdRageEffect(IsShowThirdRageEffect);
            SetIsShowThirdNormalText(IsShowThirdNormalText);
            SetIsShowThirdSkillText(IsShowThirdSkillText);
        }


        public static void SetIsShowThirdAttackSpeedLineEffect(bool IsShowThirdAttackSpeedLineEffect)
        {
            RTSQualityHelper.IsShowThirdAttackSpeedLineEffect = IsShowThirdAttackSpeedLineEffect;
        }
        public static void SetIsShowThirdAttackEffect(bool IsShowThirdAttackEffect)
        {
            RTSQualityHelper.IsShowThirdAttackEffect = IsShowThirdAttackEffect;
        }
        public static void SetIsShowThirdRageEffect(bool IsShowThirdRageEffect)
        {
            RTSQualityHelper.IsShowThirdRageEffect = IsShowThirdRageEffect;
        }
        public static void SetIsShowThirdNormalText(bool IsShowThirdNormalText)
        {
            RTSQualityHelper.IsShowThirdNormalText = IsShowThirdNormalText;
        }
        public static void SetIsShowThirdSkillText(bool IsShowThirdSkillText)
        {
            RTSQualityHelper.IsShowThirdSkillText = IsShowThirdSkillText;
        }
        public static Vector3 GetArenaPositionByPosIdAndCamp(int posId,int camp,int type)
        {
            return MarchHelper.GetArenaPositionByPosIdAndCamp(posId, camp, type);
        }

        public static void TestCrash()
        {
#if UNITY_IOS
            CrashSightAgent.TestNativeCrash();
#elif UNITY_ANDROID
            CrashSightAgent.TestJavaCrash();
            
#elif UNITY_STANDALONE_WIN
            UnityEngine.Diagnostics.Utils.ForceCrash(ForcedCrashCategory.AccessViolation);
#endif
        }

        public static void SetUserId(string playerId)
        {
            if (GameHelper.GetAOTCodeVersion() >= 20241021)
            {
                InternalSetUserId(playerId);
            }
        }

        private static void InternalSetUserId(string playerId)
        {
            if (CrashSightAgent.IsInitialized)
            {
                CrashSightAgent.SetUserId(playerId);
            }
          
        }
    }
}
